import 'package:dio/dio.dart';

//错误回调
typedef ErrorCallBack = void Function(String);

class HttpUtils {
  //method
  static const GET = 'get';
  static const POST = 'post';

  //超时时间
  static const int _timeOut = 2000;
  static Dio _dio;
  static HttpUtils _httpUtils;

  static HttpUtils get httpUtils => _httpUtils;

  factory HttpUtils(String baseUrl){
    if (_httpUtils == null) {
      _httpUtils = HttpUtils._internal(baseUrl);
    }
    return _httpUtils;
  }

  HttpUtils._internal(String baseUrl){
    _dio = Dio(BaseOptions(
        baseUrl: baseUrl, connectTimeout: _timeOut, receiveTimeout: _timeOut));
  }

  /// 添加拦截器
  addInterceptor(List<InterceptorsWrapper> interceptors) {
    _dio.interceptors.clear();
    _dio.interceptors.addAll(interceptors);
  }

  ///get请求
  Future<Response<T>> getRequest<T>(String url,
      {Map params, ErrorCallBack errorCallBack}) =>
      _request(
          url,
          GET,
          params: params,
          errorCallBack: errorCallBack);

  //post请求
  Future<Response<T>> postRequest<T>(String url,
      {Map params, ErrorCallBack errorCallBack}) =>
      _request(url, POST, params: params, errorCallBack: errorCallBack);

  // //下载
  // Future<Response<T>> downloadRequest<T>(String url,
  //     {String path, ProgressCallback progressCallback, ErrorCallBack errorCallBack}) =>
  //     _request(url, POST, );

  ///网络请求
  Future<Response<T>> _request<T>(url,
      String method, { //请求类型
        Map params, //请求参数
        Options opt, //配置选项
        ErrorCallBack errorCallBack, //错误回调
        ProgressCallback send, //上传进度监听
        ProgressCallback download, //下载进度监听
        CancelToken token // 用于取消的 token，可以多个请求绑定一个 token
      }) async {
    Response<T> response;
    try {
      if (method == GET) {
        if (params != null && params.isNotEmpty) {
          var sb = StringBuffer('?');
          params.forEach((key, value) {
            sb.write('$key=$value&');
          });
          // get 请求下拼接路径
          url += sb.toString().substring(0, sb.length - 1);
        }
        response = await _dio.get(
            url, options: opt, onReceiveProgress: download, cancelToken: token);
      } else if (method == POST) {
        response = params == null && params.isEmpty
            ?
        await _dio.post(
            url, options: opt, onReceiveProgress: download, cancelToken: token)
            :
        await _dio.post(
            url, data: params,
            options: opt,
            onReceiveProgress: download,
            cancelToken: token);
      }
      if (response.statusCode != 200 && errorCallBack != null) {
        errorCallBack('errorCode: ${response.statusCode}, errorMsg: ${response
            .statusMessage}');
      }
      return response;
    } catch (e) {
      print(e.toString());
      errorCallBack(e.toString());
    }
    return null;
  }
}
